class prop
{
protected:
	IAnimatedMeshSceneNode		Nde;		//prop Node
	stringw						Nam;		//Name of prop
	stringw						Ste;		//State of prop
	vector3df					Vlc;		//Velocity of prop
	int							Ani[][] =	//prop Animation Table
		// Appr| Dspr| Actv| Stat| Coll|
		{{   -1,   -1,   -1,   -1,   -1},
		{    -1,   -1,   -1,   -1,   -1}}
	int							VisRng;		//Visual Range Minimum
	int							ActRng;		//Active Range Minimum
	int							IntRng;		//Interactive Range Minimum

	virtual prop( IAnimatedMeshSceneNode, stringw, stringw, int[][], vector3df );
	Update()
	{
		switch( Ste )
		{
			case "Appear":
				//Animate 30 f/s
				//Logic
				//Math
				//Sound
				break;
			case "Active":
				//Animate 30 f/s
				//Logic
				//Math
				//Sound
				break;
			default "Static":
				//Animate30 f/s
				//Logic
				//Math
				//Sound
				break;
		};
		
		//Update Velocity
		this->Nde.setPosition( this->Nde.getposition().Plus( Vlc ));
	}
	virtual ~prop();
private:
	list				Cnt;	//List of props
	ITriangleselector	Slc;	//Triangle selector
};
prop::prop( IAnimatedMeshSceneNode PNde, stringw PNam, stringw PSte, int PAni[][], vector3df PVel )
{
	this->Nde	= PNde;
	this->Nam	= PNam;
	this->Ste	= PSte;
	this->Ani	= PAni;
	this->Vlc	= PVel;

	prop::Cnt.push_back( this );

	return this;
};
prop::~prop()
{
	this->Nde.remove();
	prop::Cnt.erase( this );

	return this;
};

class door : public prop
{
public:
	stringw		Swt;		//Switch Type Trip, Toggle, And, and Or
	stringw		Pat[];		//Current Switch, Switch Pattern Strings
	trigger     Trg;		//List of Triggers
	int			Ani[][] =	//Door Animation Table
		// Opng| Open| Clsn| Clos|
		{{   -1,   -1,   -1,   -1},
		{    -1,   -1,   -1,   -1}};
	door( ISceneNode DNde, stringw DNam, stringw DSte, int DAni[][], vector3df DVel )
	{
		this->Nde	= DNde;
		this->Nam	= DNam;
		this->Ste	= DSte;
		this->Ani	= DAni;
		this->Vel	= DVel;
		
		prop::Cnt.push_back( this );
		door::Cnt.push_back( this );

		return this;
	}
	Update()
	{
		switch( Ste )
		{
			case "Opening":
				//Logic
				//Animation
				//Sound
				break;
			case "Open":
				//Logic
				//Animation
				//Sound
				break;
			case "Closing":
				//Logic
				//Animation
				//Sound
				break;
			case "Closed":
				//Logic
				//Animation
				//Sound
				break;
		};
	};
	Use()
	{
		//*Check Switch Type
		switch( Swt )
		{
			case "Toggle";
				//*Compare Trigger States To Door Switch Type
				for( trigger DorTrg;  trigger this->Trg )
				{
					//*Check Door State
					if(	DorTrg.Ste == "Activated" )
					{
						//Set State to Next in Switch Pattern
						typeid( this )( Pat[int( Pat[0] )] );

						//Rotate Switch Pattern
						if(	Pat[0] < Pat.Length() - 1 )
						{
							Pat[0] = string( int( Pat[0] ) + 1 );
						}
						else if( int( Pat[0] ) > Pat.Length() - 1 )
						{
							Pat[0] = "1";
						}
						break;
					}
				}
				break;

			case "And";
				string	TrgSte[];

				for each( trigger Trg in list DorTrg )
				{
					//*Compare Trigger States

				}
				break;

			case "Or";
				break;
		default;
		}
	}
	Open()
	{
		//Logic
		//Sound
		//Special Effects
	}
	Close()
	{
		//Logic
		//Sound
		//Special Effects
	}
	~door()
	{
		door::Cnt.erase( this );
	}


private:
	list    Cnt;    //List of Doors
};

class elevator : public prop
{
public:
	vector3df				PntA;	//Point A of Path
	vector3df				PntB;	//Point B of Path
	ISceneNodeAnimator      Pth;	//Elevator Path
	float					Spd;	//Speed of Elevator
	stringw					Swt;	//Switch Type
	stringw					Pat[];	//Current Switch, Switch Pattern Strings
	list    				Trg;	//List of Triggers
	
	elevator( ISceneNode ENde, stringw ENam, stringw ESte, vector3df EPntA, vector3df EPntB, ISceneNodeAnimator EPth, float ESpd )
	{
		this->Nde	= ENde;
		this->Nam	= ENam;
		this->Ste	= ESte;
		this->PntA	= EPntA;
		this->PntB	= EPntB;
		this->Pth	= EPth;
		this->Spd	= ESpd;

		prop::Cnt.push_back( this );
		elevator::Cnt.push_back( this );

		return this;
	}
	Update()
	{
		switch( Ste )
		{
			case "End":
				//Logic
				//Animation
				//Sound
				break;
			case "Raising":
				//Logic
				//Animation
				//Sound
				break;
			case "Beggining":
				//Logic
				//Animation
				//Sound
				break;
			case "Lowering":
				//Logic
				//Animation
				//Sound
				break;
		};
	}

	Use()
	{
		if(	Ste == "Top" )
		{
			this->Lower();
		}
		else if( Ste == "Bottom" )
		{
			this->Raise();
		}
	}
	Lower()
	{
		//Logic
		//Sound
		//Special Effects
	}
	Raise()
	{
		//Logic
		//Sound
		//Special Effects
	}
	~elevator()
	{
		prop::Cnt.erase( this );
		elevator::Cnt.erase( this );

		return this;
	}

private:
	list	Cnt;	//elevator Count
};

class conveyor : public prop
{
public:
	float		Spd		//Speed of Conveyor
	stringw		Swt		//Switch Type
	stringw		Pat[]	//Switch Pattern On, Reverse, Off
	list        Trg		//List of Triggers

	conveyor( ISceneNode CNde, stringw CNam, stringw CSte, float CSpd )
	{
		this->Nde	= CNde;
		this->Nam	= CNam;
		this->Ste	= CSte;
		this->Spd	= CSpd;

		prop::Cnt.push_back( this );
		conveyor::Cnt.push_back( this );

		return this;
	};
	Update()
	{
		switch Ste;
			case "Forward":
				//Logic
				//*Check Switch Type

				//Animation
				//Sound

			case "Halted":
			 	//Logic
				//*Check Switch Type

				//Animation
				//Sound

			case "Reversed":
				//Logic
				//*Check Switch Type

				//Animation
				//Sound
		default;
	}
	Use()
	{
		if(	Ste == "Forward" )
		{
			this->Deactivate();
		}
		else if( Ste == "Halted" )
		{
			this->Activate()
		}
	}
	Activate()
	{
		//Logic
		//Sound
		//Special Effects
	}
	Reverse()
	{
		//Logic
		//Sound
		//Special Effects
	}
	Deactivate()
	{
		//Logic
		//Sound
		//Special Effects
	}
	~conveyor()
	{
		prop::Cnt.erase( this );
		conveyor::Cnt.erase( this );

		return this;
	}

private:
	list	Cnt	//List of Conveyors
};

class spawn : public prop
{
public:
	void		Obj;	//List of Objects to Spawn
	stringw		Swt;	//Switch Type
	list		Trg;	//List of Triggers

	spawn( ISceneNode SNde, stringw SNam, stringw SSte, void SObj )
	{
		this->Nde = SNde;
		this->Nam = SNam;
		this->Ste = SSte;
		this->Obj = SObj;

		prop::Cnt.push_back( this );
		spawn::Cnt.push_back( this );

		return this;
	}
	Update()
	{
	};
	Use( vector3df Pos, vector3df Rot, vector3df Scl, stringw Nam )
	{
		//Spawn
		//*Create Objects in Object List
		for each( void Spw in void Obj )
		{
			if(	Spw == class( user )) //User Node
				user( Spw )->Initialize( Pos, Rot );
			void( Spw );
			//*Add Created Object to Parent Trigger Child Counter
		}
	}
	~spawn()
	{
		spawn::Cnt.erase( this );

		return this;
	}
private:
	list	Cnt;	//List of Spawn Nodes
};

class trigger : public prop
{
public:
	stringw		Tpe;		//Type ( And, Or, Not ) null is Child Type
	stringw		Stl;		//Style ( Press, Select, Area ) null is Automatic
	stringw		Lok;		//Key Name Flag, null is Unlocked
	int			Dly;		//Activate Delay Milliseconds, - is Auto Activated
	int			DlyCnt;		//Activate Delay Counter
	int			Tmr;		//Deactivate Timer Milliseconds, - is Auto Deactivated
	int			TmrCnt;		//Deactivate Timer Counter
	int			Cld;		//Child Flag, -1 is None
	list		CldCnt;		//List of Children
	list		Prp;		//List of Props
	trigger		TrgLst[];	//Array of Triggers

	trigger( ISceneNode TNde, Stringw TNam, Stringw TSte, Stringw TTyp, Stirngw TSty, Stringw TLok, int TDly, int TTmr, void TPrp )
	{
		this->Nde	= TNde;	//Node
		this->Nam	= TNam;	//Name
		this->Ste	= TSte;	//State
		this->Lok	= TLok;	//Key
		this->Typ	= TTyp;	//Type
		this->Sty	= TSty;	//Style
		this->Dly	= TDly;	//Activate Delay
		this->Tmr	= TTmr;	//Deactivate Timer
		this->Prp	= TPrp;	//List of props


		prop::Cnt.push_back( this );
		trigger::Cnt.push_back( this );

		return this;
	}
	Update()
	{
		//Check State
		switch( this->Ste )
		{
			case "Activated":
				//Subtract Deactivate Timer
				if(	TmrCnt > 0 ) TmrCnt -= 1000 / LastFPS;
				//Auto Deactivate Trigger
				if(	TmrCnt =< 0 && Tmr < 0 ) TmrCnt = TmrCnt - TmrCnt * 2;
				break;

			case "Deactivated":
				//Subtract Activate Delay
				if(	DlyCnt > 0 ) DlyCnt -= 1000 / LastFPS;
				//Auto Activate Trigger
				if(	DlyCnt =< 0 && Dly < 0 ) DlyCnt = DlyCnt - DlyCnt * 2;
				break;
		}

		//*Check Style
		if(	Sty == "null" )
		{
			this->Use();
		}
	}
	Use()
	{
		//*Check Counters, Keys, and Children
		if(	TmrCnt =< 0 && DlyCnt =< 0 &&
			( Key.Contains( Lok ) || Lok == "" ) &&
			( Cld == -1 || CldCnt.Count() == Cld )
		{
			//Check Type Group
			if(	Typ )
			{
				string	TrgSte;	//Trigger States

				//Check Conditional Triggers
				for each( trigger T in list TrgLst )
				{
					TrgSte = TrgSte + T.Ste;
				}

				//*Check Condition Type
				switch( Typ )
				{
				case "And":
					//*All Triggers Activated
					if(	TrgSte.Contains( "Deactivated" ) == false )
					{
						//Trigger Triggers
						for each( trigger T in list TrgLst )
						{
							//Trigger Trigger
							T.Use();
						}
						//Trigger props
						for each( void O in list Prp )
						{
							//*Trigger prop
							typeid.FindMethod( Use ).Invoke( O );
						}
					}
					break;

				case "Or":
					//*Any Trigger Activated
					//Trigger Triggers
					for each( trigger T in list TrgLst )
					{
						//Trigger Trigger
						T.Use();
					}
					//Trigger props
					for each( void O in list Prp )
					{
						//*Trigger prop
						typeid.FindMethod( Use ).Invoke( O );
					}
					break;

				case "Not":
					//*All Triggers Deactivated
					if(	TrgSte.Contains( "Activated" ) == false )
					{
						//Trigger Triggers
						for each( trigger T; TrgArr )
						{
							//Trigger Trigger
							T.Use();
						}
						//Trigger props
						for each( void O; Prp )
						{
							//*Trigger prop
							typeid.FindMethod( Use ).Invoke( O );
						}
					}
					break;
				default;
				}
			}
			else
			{
				//Trigger Triggers
				for each( trigger T; TrgArr )
				{
					//Trigger Trigger
					T.Use();
				}

				//Trigger props
				for each( void O; Prp )
				{
					//Trigger prop
					typeid.FindMethod( Use ).Invoke( O );
				}
			}

			//Set Trigger State
			if(	Ste == "Deactivated" )
			{
				Ste = "Activate";
			}
			else if( Ste == "Activated" )
			{
				Ste = "Deactivate";
			}

			//Set Activate Delay
			if(	DlyCnt =< 0 && Dly > -1 )
			{
				DlyCnt = Dly;
			}
			else if( Dly =< 0 )
			{
				DlyCnt = +Dly;
			}

			//Set Deactivate Timer
			if(	TmrCnt =< 0 && Tmr > -1 )
			{
				TmrCnt = Tmr;
			}
			else if( Tmr < 0 )
			{
				TmrCnt = +Tmr;
			}
		}
	}
	~trigger()
	{
		trigger::Cnt.erase( this );

		return this;
	}

private:
	list	Cnt	//List of Triggers
};

class portal : public prop
{
public:
	
	//aabbox3d	Nde;	//Portal Bounding Box
	Slight		Lgt;	//Global Light Source
	void		Snd;	//Ambient Sound

	portal( aabbox3d PNde, Slight PLgt, void PSnd )
	{
		this->Nde	= PNde;
		this->Lgt	= PLgt;
		this->Snd	= PSnd;

		prop::Cnt.push_back( this );
		portal::Cnt.push_back( this );

		return this;
	}
	Update()
	{
	};

	~portal()
	{
		Nde.Remove();
		prop::Cnt.erase( this );
		portal::Cnt.erase( this );
		
		return this;
	}
private:
	
	list	Cnt;
};
